home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 …ember: Reference Library / Dev.CD Dec 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 28 / develop issue 28 code / sketch / source / appleevent / oslclassapplication.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-25  |  24.4 KB  |  1,008 lines

  1. /****************************************************************************
  2.  * 
  3.  * OSLClassApplication.c
  4.  * 
  5.  * OSL support for the cApplication Apple Event Registry object
  6.  *
  7.  ****************************************************************************/
  8.  
  9. #include "Sketch.h"
  10.  
  11. #include "OSLClassApplication.h"
  12.  
  13. #include "AERCoreSuite.h"
  14. #include "AppleEvent.h"
  15. #include "OSLHelpers.h"
  16.  
  17. #include "DocumentADT.h"    // for CountDocuments()
  18. #include "WindowUtils.h"    // for CountWindows()
  19.  
  20. #include "StringUtils.h"    // for VersionString()
  21.  
  22. // ----------------------------------------------------------------------------
  23. //                      Core Suite Object Event handlers
  24. // ----------------------------------------------------------------------------
  25.  
  26. static OSErr HandleClose        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  27. static OSErr HandleCount        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  28. static OSErr HandleDataSize    (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  29. static OSErr HandleDelete        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  30. static OSErr HandleDuplicate    (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  31. static OSErr HandleExists        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  32. static OSErr HandleGetData        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  33. static OSErr HandleMake            (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  34. static OSErr HandleMove            (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  35. static OSErr HandleOpen            (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  36. static OSErr HandlePrint        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  37. static OSErr HandleQuit            (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  38. static OSErr HandleSave            (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  39. static OSErr HandleSetData        (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
  40.  
  41. // ----------------------------------------------------------------------------
  42. //                      Core Suite Object Accessor functions
  43. // ----------------------------------------------------------------------------
  44.  
  45. static pascal OSErr 
  46. PropertyFromApplicationAccessor(    
  47.         DescType        desiredClass,
  48.          AEDesc        *containerToken,
  49.         DescType        containerClass,
  50.         DescType        keyForm,
  51.         AEDesc        *keyData,
  52.         AEDesc        *resultToken,
  53.         long             refCon);
  54.  
  55. static OSErr         GetDataFromObject        (const AEDesc *token, AEDesc *data);
  56. static OSErr         SetDataForObject        (const AEDesc *token, AEDesc *data);
  57.  
  58. static Boolean        CanGetProperty            (DescType propertyCode);
  59. static Boolean        CanSetProperty            (DescType propertyCode);
  60.  
  61. /*****************************************************************************
  62.  * 
  63.  * ApplicationEventDispatcher
  64.  *
  65.  *    Handles all OSL messages that cApplication should handle
  66.  * 
  67.  *****************************************************************************/
  68.  
  69. OSErr
  70. ApplicationEventDispatcher(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
  71. {
  72.     #pragma unused (refcon)
  73.  
  74.     OSErr error                 = noErr;
  75.     
  76.     AEEventID    eventID;
  77.     OSType        typeCode;
  78.     Size            actualSize     = 0L;
  79.     
  80.     // Get the event ID
  81.     
  82.     error = AEGetAttributePtr(appleEvent, 
  83.                                       keyEventIDAttr, 
  84.                                       typeType, 
  85.                                       &typeCode, 
  86.                                       (Ptr)&eventID, 
  87.                                       sizeof(eventID), 
  88.                                       &actualSize);
  89.     if (error != noErr) {
  90.         return error;
  91.     }
  92.     
  93.     switch (eventID) {
  94.     
  95.         case kAEClone:
  96.             error = HandleDuplicate(token, appleEvent, reply);
  97.             break;
  98.             
  99.         case kAEClose:
  100.             error = HandleClose(token, appleEvent, reply);
  101.             break;
  102.             
  103.         case kAECountElements:
  104.             error = HandleCount(token, appleEvent, reply);
  105.             break;
  106.             
  107.         case kAECreateElement:
  108.             error = HandleMake(token, appleEvent, reply);
  109.             break;
  110.             
  111.         case kAEDelete:
  112.             error = HandleDelete(token, appleEvent, reply);
  113.             break;
  114.             
  115.         case kAEDoObjectsExist:
  116.             error = HandleExists(token, appleEvent, reply);
  117.             break;
  118.             
  119.         case kAEGetData:
  120.             error = HandleGetData(token, appleEvent, reply);
  121.             break;
  122.             
  123.         case kAEGetDataSize:
  124.             error = HandleDataSize(token, appleEvent, reply);
  125.             break;
  126.             
  127.         case kAEMove:
  128.             error = HandleMove(token, appleEvent, reply);
  129.             break;
  130.             
  131.         case kAEOpen:
  132.             error = HandleOpen(token, appleEvent, reply);
  133.             break;
  134.             
  135.         case kAEPrint:
  136.             error = HandlePrint(token, appleEvent, reply);
  137.             break;
  138.             
  139.         case kAEQuitApplication:
  140.             error = HandleQuit(token, appleEvent, reply);
  141.             break;
  142.             
  143.         case kAESave:
  144.             error = HandleSave(token, appleEvent, reply);
  145.             break;
  146.             
  147.         case kAESetData:
  148.             error = HandleSetData(token, appleEvent, reply);
  149.             break;
  150.  
  151.         default:
  152.             error = errAEEventNotHandled;
  153.             break;
  154.     }
  155.  
  156.     if (error != noErr)
  157.         PutReplyErrorNumber(reply, error);
  158.     
  159.     return error;
  160. }
  161.  
  162. #pragma mark -
  163. // ----------------------------------------------------------------------------
  164. //                      Core Suite Object Event handlers
  165. // ----------------------------------------------------------------------------
  166.  
  167. static OSErr 
  168. HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  169. {
  170.     #pragma unused (token, reply)
  171.  
  172.     OSErr         error     = noErr;
  173.     
  174.     DescType        typeCode = 0L;
  175.     
  176.     AEDesc        saving    = {typeNull, nil};
  177.     AEDesc        savingIn = {typeNull, nil};
  178.     
  179.     AEDesc      *ptrToSaving    = NULL;
  180.     AEDesc      *ptrToSavingIn = NULL;
  181.     
  182.     // Extract the [saving yes/no/ask] optional parameter, if present
  183.     
  184.     error = AEGetParamDesc(appleEvent, 
  185.                                   keyAESaveOptions, 
  186.                                   typeWildCard, 
  187.                                   &saving);
  188.                                   
  189.     if (error != errAEDescNotFound && error != noErr)
  190.         goto Cleanup;
  191.         
  192.     ptrToSaving = &saving;
  193.     
  194.     // Extract the [saving in <alias>] optional parameter, if present
  195.     
  196.     error = AEGetParamDesc(appleEvent, 
  197.                                   keyAEFile, 
  198.                                   typeWildCard, 
  199.                                   &savingIn);
  200.                                   
  201.     if (error != errAEDescNotFound && error != noErr)
  202.         goto Cleanup;
  203.         
  204.     ptrToSavingIn = &savingIn;
  205.     
  206.     // Check for any required parameters we may have missed
  207.     
  208.     error = CheckForUnusedParameters(appleEvent);
  209.     if (error != noErr)
  210.         goto Cleanup;
  211.         
  212.     // Now, do the application-related work
  213.     SysBeep(2);
  214.         
  215.  
  216. Cleanup:
  217.     AEDisposeDesc(&saving);
  218.     AEDisposeDesc(&savingIn);
  219.         
  220.     return error;
  221. }
  222.  
  223. // ----------------------------------------------------------------------------
  224.     
  225. static OSErr 
  226. HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  227. {
  228.     OSErr        error                 = noErr;    
  229.     long         numberOfObjects     = 0L;
  230.  
  231.     DescType    objectClass;
  232.  
  233.     // Get the class of object that we will count
  234.  
  235.     error = GetObjectClassFromAppleEvent(appleEvent, &objectClass);
  236.  
  237.     if (error) 
  238.         goto CleanUp;
  239.  
  240.     // Make sure we got & handled all of the required paramters
  241.     
  242.     error = CheckForUnusedParameters(appleEvent);
  243.     if (error) 
  244.         goto CleanUp;
  245.     
  246.     // Send back the results
  247.     
  248.     if (reply->dataHandle)
  249.     {    
  250.         if (TokenContainsTokenList(token))
  251.         {
  252.             error = AECountItems(token, &numberOfObjects);
  253.             if (error == noErr)
  254.                     error = AEPutParamPtr(reply, keyAEResult, 
  255.                                                  typeLongInteger, 
  256.                                                  (Ptr)&numberOfObjects, 
  257.                                                  sizeof(long));
  258.         }
  259.         else
  260.         {    
  261.             switch (objectClass)
  262.             {
  263.                 case cDocument:
  264.                     numberOfObjects = CountDocuments(GetDocumentList());
  265.                     error = AEPutParamPtr(reply, 
  266.                                                  keyAEResult, 
  267.                                                  typeLongInteger, 
  268.                                                  (Ptr)&numberOfObjects, 
  269.                                                  sizeof(long));
  270.                     break;
  271.  
  272.                 case cWindow:
  273.                     numberOfObjects = CountWindows();
  274.                     error = AEPutParamPtr(reply, 
  275.                                                  keyAEResult, 
  276.                                                  typeLongInteger, 
  277.                                                  (Ptr)&numberOfObjects, 
  278.                                                  sizeof(long));
  279.                     break;
  280.                                         
  281.                 default:
  282.                     error = errAEEventNotHandled;
  283.                     break;
  284.             }
  285.         }
  286.     }            
  287.  
  288. CleanUp:
  289.  
  290.     return error;
  291.     
  292. }
  293.  
  294. // ----------------------------------------------------------------------------
  295.  
  296. static OSErr 
  297. HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  298. {
  299.     OSErr     error = noErr;
  300.     AEDesc    data     = {typeNull, nil};    
  301.     long        size  = 0L;
  302.     
  303.     // First, get the data
  304.     error = HandleGetData(token, appleEvent, reply);
  305.     
  306.     // now, extract it from the reply
  307.     
  308.     if (error == noErr)
  309.         error = AEGetKeyDesc(reply, keyDirectObject, typeWildCard, &data);
  310.         
  311.     if (error == noErr)
  312.     {
  313.         if (data.dataHandle != nil)
  314.         {
  315.             size = GetHandleSize(data.dataHandle);
  316.         }                         
  317.         error = AEPutParamPtr(reply, 
  318.                                      keyAEResult, 
  319.                                      typeLongInteger, 
  320.                                      (Ptr)&size, 
  321.                                      sizeof(long));
  322.     }
  323.  
  324.     if (error != noErr)
  325.         PutReplyErrorNumber(reply, error);
  326.     
  327.     AEDisposeDesc(&data);
  328.     
  329.     return error;
  330.  
  331. }
  332.  
  333. // ----------------------------------------------------------------------------
  334. // All attempts to delete an empty list are handled here
  335. // Application contains documents and windows, and they can't be deleted
  336.  
  337. static OSErr 
  338. HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  339. {
  340.     #pragma unused (appleEvent, reply)
  341.  
  342.     OSErr error = noErr;
  343.         
  344.     if (TokenContainsTokenList(token))
  345.     {
  346.         long             numItems;
  347.         
  348.         AECountItems(token, &numItems);
  349.  
  350.         if (numItems > 0)
  351.             error = errAEEventNotHandled;
  352.     }
  353.  
  354.     return error;
  355. }
  356.  
  357. // ----------------------------------------------------------------------------
  358.  
  359. static OSErr 
  360. HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  361. {
  362.     #pragma unused (token, appleEvent, reply)
  363.  
  364.     OSErr error = errAEEventNotHandled;
  365.     
  366.     return error;
  367. }
  368.  
  369. // ----------------------------------------------------------------------------
  370. // If <referenceToObject> exists...
  371. // The AEResolve() function in AERCoreSuite.c will already have filtered
  372. // out all cases where the object did not exist, so this function should
  373. // always return TRUE.
  374.  
  375. static OSErr 
  376. HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  377. {
  378.     #pragma unused (token, appleEvent)
  379.  
  380.     OSErr error         = noErr;
  381.     Boolean foundIt    = true;
  382.  
  383.     error = AEPutParamPtr(reply, 
  384.                      keyAEResult, 
  385.                      typeBoolean, 
  386.                      (Ptr)&foundIt, 
  387.                      sizeof(Boolean));
  388.         
  389.     return error;
  390. }
  391.  
  392. // ----------------------------------------------------------------------------
  393.  
  394. static OSErr 
  395. HandleGetData(AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply)
  396. {
  397.     #pragma unused (appleEvent)
  398.  
  399.     OSErr             error             = noErr;    
  400.     AEDesc            data               = {typeNull, nil};
  401.     DescType             propertyCode;
  402.     long                numItems;
  403.     
  404.     switch (tokenOrTokenList->descriptorType)
  405.     {
  406.         case cProperty:
  407.             propertyCode = ExtractPropertyCodeFromToken(tokenOrTokenList);
  408.     
  409.             error = GetDataFromObject(tokenOrTokenList, &data);
  410.             if (error == noErr)
  411.                 error = AEPutKeyDesc(reply, keyDirectObject, &data);                    // return the requested data
  412.             break;
  413.             
  414.         case typeAEList:
  415.             // Usually, this should be an EMPTY list
  416.             error = AECountItems(tokenOrTokenList, &numItems);
  417.             error = AEPutKeyDesc(reply, keyDirectObject, tokenOrTokenList);
  418.             break;
  419.             
  420.         default:
  421.             break;
  422.     }
  423.  
  424.     AEDisposeDesc(&data);
  425.     
  426.     return error;
  427. }
  428.  
  429. // ----------------------------------------------------------------------------
  430.  
  431. static OSErr 
  432. HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  433. {
  434.     #pragma unused (token, appleEvent, reply)
  435.  
  436.     OSErr error = errAEEventNotHandled;
  437.     
  438.     return error;
  439. }
  440.  
  441. // ----------------------------------------------------------------------------
  442.  
  443. static OSErr 
  444. HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  445. {
  446.     #pragma unused (token, appleEvent, reply)
  447.  
  448.     OSErr error = errAEEventNotHandled;
  449.     
  450.     return error;
  451. }
  452.  
  453. // ----------------------------------------------------------------------------
  454.  
  455. static OSErr 
  456. HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  457. {
  458.     #pragma unused (token, appleEvent, reply)
  459.  
  460.     OSErr error = errAEEventNotHandled;
  461.     
  462.     return error;
  463. }
  464.  
  465. // ----------------------------------------------------------------------------
  466.  
  467. static OSErr 
  468. HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  469. {
  470.     #pragma unused (token, appleEvent, reply)
  471.  
  472.     OSErr error = errAEEventNotHandled;
  473.     
  474.     return error;
  475. }
  476.  
  477. // ----------------------------------------------------------------------------
  478.  
  479. static OSErr 
  480. HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  481. {
  482.     #pragma unused (token, appleEvent, reply)
  483.  
  484.     OSErr error = errAEEventNotHandled;
  485.     
  486.     return error;
  487. }
  488.  
  489. // ----------------------------------------------------------------------------
  490.  
  491. static OSErr 
  492. HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  493. {
  494.     #pragma unused (token, appleEvent, reply)
  495.  
  496.     OSErr error = errAEEventNotHandled;
  497.     
  498.     return error;
  499. }
  500.  
  501. // ----------------------------------------------------------------------------
  502.  
  503. static OSErr 
  504. HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
  505. {
  506.     OSErr             error         = noErr;    
  507.     AEDesc            tokenData   = {typeNull, nil};
  508.     
  509.     DescType             propertyCode;
  510.             
  511.     if (token->descriptorType == cProperty)
  512.     {
  513.         propertyCode = ExtractPropertyCodeFromToken(token);
  514.  
  515.         if (CanSetProperty(propertyCode))
  516.         {
  517.             // only the clipboard property is writeable
  518.             // the clipboard data should be in a list, so we extract that list
  519.             
  520.             switch (propertyCode)
  521.             {
  522.                 case pClipboard:
  523.                     error = AEGetKeyDesc(appleEvent, keyAEData, typeAEList, &tokenData);
  524.                     if (error == noErr)
  525.                         error = SetDataForObject(token, &tokenData);
  526.                     if (error == noErr)
  527.                         error = AEPutKeyDesc(reply, keyDirectObject, &tokenData);    // return the requested data
  528.                     break;
  529.                     
  530.                 default:
  531.                     error = errAENotModifiable;  // "Can't set xxx to nnn"
  532.                     break;
  533.             }
  534.         }
  535.         else
  536.         {
  537.             error = errAENotModifiable;  
  538.         }
  539.     }
  540.     else
  541.     {
  542.         error = errAEEventNotHandled;
  543.     }
  544.     
  545.     AEDisposeDesc(&tokenData);
  546.     
  547.     return error;
  548. }
  549.  
  550. #pragma mark -
  551. // -----------------------------------------------------------------------------
  552. //                                                Object Accessors
  553. //------------------------------------------------------------------------------
  554.  
  555. OSErr 
  556. InstallApplicationAccessors(void)
  557. {
  558.  
  559.     OSErr error;
  560.     
  561.     error = AEInstallObjectAccessor(cProperty, 
  562.                                                 typeNull, 
  563.                                                 NewOSLAccessorProc(PropertyFromApplicationAccessor), 
  564.                                                 0L, 
  565.                                                 false);
  566.     return error;
  567. }
  568.  
  569. #pragma mark -
  570. //----------------------------------------------------------------------------------//
  571. //    Return a token that contains the property type and nil to represent the null        //
  572. //    container (the application).                                                                        //
  573. //----------------------------------------------------------------------------------//
  574.  
  575. pascal OSErr 
  576. PropertyFromApplicationAccessor(    DescType        desiredClass,            // cProperty
  577.                                            AEDesc*        containerToken,
  578.                                         DescType        containerClass,        // cApplication 
  579.                                         DescType        keyForm,
  580.                                         AEDesc*        keyData,
  581.                                         AEDesc*        resultToken,
  582.                                         long             refCon)
  583. {    
  584.     #pragma unused (desiredClass, containerToken, containerClass, keyForm, refCon)
  585.  
  586.     OSErr                    error;
  587.     CoreTokenRecord     token;
  588.     DescType                requestedProperty = **(DescType**)keyData->dataHandle;
  589.     
  590.     InitCoreTokenRecord(&token);
  591.  
  592.     token.dispatchClass   = cApplication;
  593.     token.objectClass     = cApplication;
  594.     token.propertyCode    = requestedProperty;
  595.  
  596.     if (CanGetProperty(requestedProperty) || CanSetProperty(requestedProperty))
  597.     {
  598.         error = AECreateDesc(cProperty, (Ptr)&token, sizeof(CoreTokenRecord), resultToken); 
  599.     }
  600.     else
  601.     {
  602.         error = errAEEventNotHandled;
  603.     }
  604.     
  605.     return error;
  606. }
  607.  
  608. //----------------------------------------------------------------------------------
  609. //                                           GetDataFromObject
  610. //----------------------------------------------------------------------------------
  611.  
  612. static OSErr 
  613. GetDataFromObject(const AEDesc *token, AEDesc *data)
  614. {
  615.  
  616.     OSErr                    error                    = noErr;
  617.     
  618.     Str255                        applicationName = "\p";
  619.     Str255                        versionString;
  620.     
  621.     ProcessSerialNumber        applicationProcessNumber;
  622.     ProcessInfoRec                applicationInfo;
  623.     FSSpec                        appFSSpec;
  624.  
  625.     Boolean                   isFrontProcess = !IsCurrentProcessInBackground();
  626.     
  627.     DescType                        aDescType            = cApplication;
  628.     
  629.     long                            documentNumber        = 0L;
  630.     unsigned long                elementNumber        = 0L;
  631.     
  632.     DocumentReference         document                = nil;
  633.     ElementReference          element                = nil;
  634.     
  635.     Boolean                        usePropertyCode    = ExtractUsePropertyCodeFromToken(token);
  636.     DescType                        propertyCode;
  637.     
  638.     long                             free;
  639.     long                             contiguous;
  640.     unsigned long                 ticks;
  641.  
  642.     if (usePropertyCode)
  643.     {
  644.         error = GetCurrentProcess(&applicationProcessNumber);    
  645.         
  646.         if (error == noErr)
  647.         {
  648.             applicationInfo.processInfoLength     = sizeof(ProcessInfoRec);
  649.             applicationInfo.processName             = applicationName;
  650.             applicationInfo.processAppSpec         = &appFSSpec;
  651.             error = GetProcessInformation(&applicationProcessNumber, &applicationInfo);
  652.         }
  653.                     
  654.         versionString[0] = 0;
  655.         VersionString(2, versionString);
  656.  
  657.         PurgeSpace(&free, &contiguous);
  658.                     
  659.         ticks = TickCount();
  660.  
  661.         propertyCode = ExtractPropertyCodeFromToken(token);
  662.         
  663.         switch (propertyCode)
  664.         {
  665.             case pProperties:
  666.                 error = AECreateList(NULL, 0L, true, data);
  667.                 if (error != noErr)
  668.                     goto CleanUp;
  669.  
  670.                 error = AEPutKeyPtr(data, pObjectType,         typeType,             &aDescType, sizeof(DescType));
  671.  
  672.                 error = AEPutKeyPtr(data, pName,               typeChar,             &applicationName[1], applicationName[0]);
  673.                 
  674.                 error = AEPutKeyPtr(data, pVersion,            typeChar,             &versionString[1], versionString[0]);
  675.  
  676.                 error = AEPutKeyPtr(data, pIsFrontProcess,    typeBoolean,         &isFrontProcess, sizeof(Boolean));
  677.  
  678.                 error = AEPutKeyPtr(data, pFreeMemory,            typeLongInteger,     &free, sizeof(long));
  679.  
  680.                 error = AEPutKeyPtr(data, pLargestFreeBlock,    typeLongInteger,     &contiguous, sizeof(long));
  681.  
  682.                 error = AEPutKeyPtr(data, pTicks,                typeLongInteger,     &ticks, sizeof(long));
  683.  
  684.                 break;
  685.                 
  686.             case pBestType:
  687.             case pClass:
  688.             case pDefaultType:
  689.             case pObjectType:
  690.                 error = AECreateDesc(typeType, &aDescType, sizeof(DescType), data);
  691.                 break;
  692.                 
  693.             case pName:    
  694.                 error = AECreateDesc(typeChar, &applicationName[1], applicationName[0], data);
  695.                 break;
  696.  
  697.             case pVersion:
  698.                 error = AECreateDesc(typeChar, &versionString[1], versionString[0], data);
  699.                 break;
  700.  
  701.             case pIsFrontProcess:
  702.                 error = AECreateDesc(typeBoolean, &isFrontProcess, sizeof(Boolean), data);
  703.                 break;
  704.  
  705.             case pFreeMemory:
  706.                 error = AECreateDesc(typeLongInteger, &free, sizeof(long), data);
  707.                 break;
  708.                 
  709.             case pLargestFreeBlock:
  710.                 error = AECreateDesc(typeLongInteger, &contiguous, sizeof(long), data);
  711.                 break;
  712.                 
  713.             case pTicks:
  714.                 error = AECreateDesc(typeLongInteger, &ticks, sizeof(long), data);
  715.                 break;
  716.                 
  717.             case pClipboard:
  718.                 {
  719.                     //    Return all of the items currently on the clipboard.
  720.                     //    The returned information is an AEList, and each data type
  721.                     //    on the scrap gets its own entry in the list
  722.                     //    Since the OS doesn't supply the tools for getting all
  723.                     //    of the types in the scrap, we have to scan the scrap ourselves
  724.  
  725.                     char            *scrapPtr;
  726.                     char            *scrapEnd;
  727.                     PScrapStuff     scrapInfo;
  728.                     OSType         itemType;
  729.                     long             itemLength;
  730.                     long             index;
  731.                     
  732.                     error = AECreateList(NULL, 0, false, data);
  733.                     if (error != noErr) 
  734.                         break;
  735.                     
  736.                     error = LoadScrap();                                        //    Make sure the scrap is in memory, not on disk.
  737.                     if (error != noErr) 
  738.                         break;
  739.                     
  740.                     scrapInfo = InfoScrap();                                //    Get the base address of the scrap in RAM
  741.                     MoveHHi(scrapInfo->scrapHandle);
  742.                     HLock  (scrapInfo->scrapHandle);                        // ...and lock it
  743.                     
  744.                     scrapPtr = (char *)*scrapInfo->scrapHandle;
  745.                     scrapEnd = scrapPtr + scrapInfo->scrapSize;
  746.                     
  747.                     // scan the scrap in memory and extract each scrap type
  748.                     
  749.                     index = 1;
  750.                     while (scrapPtr < scrapEnd) 
  751.                     {
  752.                         itemType = *(OSType *)scrapPtr;
  753.                         scrapPtr += sizeof(itemType);
  754.                         itemLength = *(long *)scrapPtr;
  755.                         scrapPtr += sizeof(itemLength);
  756.                         
  757.                         // Move this information into the next entry on the list
  758.                         error = AEPutPtr(data, index, itemType, scrapPtr, itemLength);
  759.                         if (error != noErr) 
  760.                             return error;
  761.                             
  762.                         index++;
  763.                         
  764.                         // Adjust the pointer to the start of the next item
  765.                         
  766.                         if (itemLength & 1) 
  767.                             itemLength++;                                         // If it's odd, make it even
  768.                             
  769.                         scrapPtr += itemLength;
  770.                     }
  771.                     HUnlock  (scrapInfo->scrapHandle);
  772.                 } 
  773.                 break;
  774.  
  775.             default:
  776.                 error = errAECantSupplyType;
  777.         }
  778.     }
  779.  
  780. CleanUp:
  781.  
  782.     return error;
  783. }
  784.  
  785. //----------------------------------------------------------------------------------
  786. //                                       SetDataForObject
  787. //----------------------------------------------------------------------------------
  788. // Assumption: HandleSetData() has already filtered out all attempts
  789. // to write to a read-only property.
  790.  
  791. static OSErr 
  792. SetDataForObject(const AEDesc *token, AEDesc *data)
  793. {
  794.  
  795.     OSErr                    error            = noErr;
  796.  
  797.     long                    numItems;
  798.     long                    index;
  799.     AEDesc                currentItemDesc = {typeNull, nil};
  800.    AEKeyword             theAEKeyword;
  801.  
  802.     Boolean                usePropertyCode     = ExtractUsePropertyCodeFromToken(token);
  803.     DescType                propertyCode;
  804.     
  805.     if (usePropertyCode)
  806.     {
  807.         propertyCode = ExtractPropertyCodeFromToken(token);
  808.         
  809.         switch (propertyCode)
  810.         {
  811.             // the clipboard is the only writeable property for the application object
  812.             case pClipboard:
  813.                 //    The data should be an AE list containing a series of things to be placed on the
  814.                 //    clipboard. The data type of each item is also the clipboard type for that data
  815.                 
  816.                 error = ZeroScrap();
  817.                 if (error != noErr) 
  818.                     break;
  819.                 
  820.                 AECountItems(data, &numItems);
  821.                 
  822.                 //  Copy each item onto the clipboard
  823.                 
  824.                 for (index = 1; index <= numItems; index++) 
  825.                 {
  826.                     error = AEGetNthDesc(data, index, typeWildCard, &theAEKeyword, ¤tItemDesc);
  827.                     if (error != noErr) {
  828.                         if (currentItemDesc.dataHandle != NULL) 
  829.                             AEDisposeDesc(¤tItemDesc);
  830.                         break;
  831.                     }
  832.                     HLock(currentItemDesc.dataHandle);
  833.                     error = PutScrap(GetHandleSize(currentItemDesc.dataHandle), 
  834.                                           currentItemDesc.descriptorType,
  835.                                         *currentItemDesc.dataHandle);
  836.  
  837.                     AEDisposeDesc(¤tItemDesc);
  838.                     currentItemDesc.dataHandle = nil;
  839.                 }
  840.                 break;
  841.                 
  842.             default:
  843.                 error = errAENotModifiable;
  844.         }
  845.     }
  846.     
  847.     return error;
  848. }
  849.  
  850. //----------------------------------------------------------------------------------
  851. // creates an ospec for the each selected object in the frontmost ad document
  852. // and inserts each such ospec into a list and returns in in the data parameter.
  853.  
  854. static OSErr 
  855. GetApplicationSelection(const AEDesc *token, AEDesc *data)
  856. {
  857.     #pragma unused (token, data)
  858.  
  859.     OSErr                    error     = noErr;
  860. /*
  861.     DocumentReference document;
  862.     ElementReference  element;
  863.     AEDesc                 ospec     = {typeNull, nil};
  864.  
  865.     // Make sure we have at least one document
  866.     
  867.     document = GetFrontDocument(GetDocumentList());
  868.     
  869.     if (document == nil)
  870.     {
  871.         error = errAENoSuchObject;
  872.         goto CleanUp;
  873.     }
  874.     
  875.     // Make sure that document has at least one selected element
  876.     
  877.     element = GetFirstSelectedElement(GetDocumentElementList(document));
  878.  
  879.     if (element == nil)
  880.     {
  881.         error = errAENoUserSelection;
  882.         goto CleanUp;
  883.     }
  884.  
  885.     error = AECreateList(nil, (Size)0, false, data);             // create an empty list to hold the ospec(s)
  886.  
  887.     if (error != noErr)
  888.         goto CleanUp;
  889.  
  890.     while (error == noErr && element != nil)
  891.     {
  892.         error = CreateElementOSpec(document, element, &ospec);
  893.         
  894.         if (error == noErr)
  895.         {
  896.             error = AEPutDesc(data, 0, &ospec);
  897.             AEDisposeDesc(&ospec);
  898.         }
  899.         
  900.         element = GetNextSelectedElement(element);
  901.     }
  902.     
  903.     
  904. CleanUp:
  905.  
  906.     AEDisposeDesc(&ospec);
  907. */
  908.         
  909.     return error;
  910. }
  911.  
  912. #pragma mark -
  913. //----------------------------------------------------------------------------------
  914.  
  915. static Boolean
  916. CanGetProperty(DescType propertyCode)
  917. {
  918.     Boolean result = false;
  919.     
  920.     switch (propertyCode)
  921.     {
  922.         // Properties we can get:
  923.  
  924.         case pBestType:
  925.         case pClass:
  926.         case pDefaultType:
  927.         case pObjectType:
  928.             
  929.         case pProperties:
  930.         
  931.         case pFreeMemory:
  932.         case pLargestFreeBlock:
  933.         case pTicks:
  934.  
  935.         case pIsFrontProcess:
  936.         case pName:
  937.         case pVersion:
  938.         case pInsertionLoc:
  939.         case pSelection:
  940.         case pUserSelection:
  941.             result = true;
  942.             break;
  943.             
  944.         // Properties we should be able to get, but they're not implemented yet:
  945.                     
  946.         // Properties we should not be able to get:
  947.         
  948.         default:
  949.             result = false;
  950.             break;
  951.     }
  952.     
  953.     return result;
  954. }
  955.  
  956.  
  957. //----------------------------------------------------------------------------------
  958.  
  959. static Boolean
  960. CanSetProperty(DescType propertyCode)
  961. {
  962.     Boolean result = false;
  963.     
  964.     switch (propertyCode)
  965.     {
  966.         // Properties we can set:
  967.         
  968.         case pClipboard:
  969.             result = true;
  970.             break;
  971.             
  972.         // Properties we should be able to set, but they're not implemented yet:
  973.         
  974.                     
  975.         // Properties that are read-only
  976.  
  977.         case pBestType:
  978.         case pClass:
  979.         case pDefaultType:
  980.         case pObjectType:
  981.         
  982.         case pProperties:
  983.  
  984.         case pFreeMemory:
  985.         case pLargestFreeBlock:
  986.         case pTicks:
  987.  
  988.         case pIsFrontProcess:
  989.         case pName:
  990.         case pVersion:
  991.         case pInsertionLoc:
  992.         case pSelection:
  993.         case pUserSelection:
  994.         default:
  995.             result = false;
  996.             break;
  997.     }
  998.     
  999.     return result;
  1000. }
  1001.  
  1002.  
  1003. //----------------------------------------------------------------------------------
  1004.  
  1005.  
  1006.  
  1007.  
  1008.